<?php

namespace app\service;

use think\facade\Config;
use think\facade\Log;
use think\facade\Lang;

class WechatService
{
    // 微信网页授权相关URL常量
    const AUTH_URL = 'https://open.weixin.qq.com/connect/qrconnect'; // PC扫码登录URL
    const AUTH_URL_H5 = 'https://open.weixin.qq.com/connect/oauth2/authorize'; // 微信H5授权URL
    const ACCESS_TOKEN_URL = 'https://api.weixin.qq.com/sns/oauth2/access_token';
    const USER_INFO_URL = 'https://api.weixin.qq.com/sns/userinfo';

    /**
     * 生成微信登录授权URL.
     *
     * @param string $state    CSRF防护参数
     * @param bool   $isWechat 是否在微信浏览器中
     * @param bool   $isMobile 是否在移动设备上
     *
     * @return string 授权URL
     */
    public static function getAuthUrl($state = '', $isWechat = false, $isMobile = false)
    {
        // 获取微信配置
        $wechatConfig = Config::get('app.wechat');
        if (empty($wechatConfig) || empty($wechatConfig['app_id'])) {
            Log::error('微信配置不存在或不完整');

            return '';
        }

        // 根据设备类型选择合适的AppID和scope
        $app_id = $wechatConfig['app_id']; // 默认使用PC端AppID
        $scope = $wechatConfig['scope']; // 默认使用PC端scope
        $authUrl = self::AUTH_URL; // 默认使用PC端扫码登录URL
        
        // 如果是在微信浏览器中的移动设备，使用公众号AppID和scope
        if ($isWechat && $isMobile) {
            $app_id = $wechatConfig['app_id_h5'];
            $scope = $wechatConfig['scope_h5'];
            $authUrl = self::AUTH_URL_H5;
            
            Log::info(Lang::get('using_wechat_h5_auth_mode'));
        } else {
            Log::info(Lang::get('using_pc_qrcode_login_mode'));
        }
        
        // 构造回调URL（注意此处URL需要进行编码）
        $redirectUri = url('v6/login/wechatCallback', [], true, true);

        // 记录日志
        $deviceInfo = [
            'isWechat' => $isWechat,
            'isMobile' => $isMobile,
            'app_id' => $app_id,
            'auth_type' => $isWechat && $isMobile ? 'H5' : 'PC'
        ];
        Log::info(Lang::get('wechat_auth_device_info').': '.json_encode($deviceInfo));

        // 构造授权URL
        $url = $authUrl;
        $url .= '?appid='.$app_id;
        $url .= '&redirect_uri='.urlencode($redirectUri);
        $url .= '&response_type=code';
        $url .= '&scope='.$scope;
        $url .= '&state='.$state;
        $url .= '#wechat_redirect';

        return $url;
    }

    /**
     * 通过授权码获取访问令牌.
     *
     * @param string $code 授权码
     * @param bool   $isWechat 是否在微信浏览器中
     * @param bool   $isMobile 是否在移动设备上
     *
     * @return array 包含access_token、openid等信息的数组
     */
    public static function getAccessToken($code, $isWechat = false, $isMobile = false)
    {
        // 获取微信配置
        $wechatConfig = Config::get('app.wechat');
        if (empty($wechatConfig) || empty($wechatConfig['app_id']) || empty($wechatConfig['app_secret'])) {
            Log::error('微信配置不存在或不完整');

            return [];
        }
        
        // 根据设备类型选择合适的AppID和Secret
        $app_id = $wechatConfig['app_id']; // 默认使用PC端AppID
        $app_secret = $wechatConfig['app_secret']; // 默认使用PC端Secret
        
        // 如果是在微信浏览器中的移动设备，使用公众号AppID和Secret
        if ($isWechat && $isMobile) {
            $app_id = $wechatConfig['app_id_h5'];
            $app_secret = $wechatConfig['app_secret_h5'];
            
            Log::info('获取访问令牌使用微信内浏览器H5模式');
        } else {
            Log::info('获取访问令牌使用PC端模式');
        }

        // 记录设备信息日志
        $deviceInfo = [
            'isWechat' => $isWechat,
            'isMobile' => $isMobile,
            'app_id' => $app_id,
            'auth_type' => $isWechat && $isMobile ? 'H5' : 'PC'
        ];
        Log::info('获取访问令牌设备信息: '.json_encode($deviceInfo));

        // 构造请求URL
        $url = self::ACCESS_TOKEN_URL;
        $url .= '?appid='.$app_id;
        $url .= '&secret='.$app_secret;
        $url .= '&code='.$code;
        $url .= '&grant_type=authorization_code';

        // 发起HTTP请求
        $result = self::httpGet($url);

        // 解析结果
        $result = json_decode($result, true);
        if (!$result || isset($result['errcode'])) {
            Log::error('获取微信access_token失败: '.json_encode($result, JSON_UNESCAPED_UNICODE));

            return $result ?: [];
        }

        return $result;
    }

    /**
     * 获取微信用户信息.
     *
     * @param string $accessToken 访问令牌
     * @param string $openid      用户openid
     *
     * @return array 用户信息数组
     */
    public static function getUserInfo($accessToken, $openid)
    {
        // 构造请求URL
        $url = self::USER_INFO_URL;
        $url .= '?access_token='.$accessToken;
        $url .= '&openid='.$openid;
        $url .= '&lang=zh_CN';

        // 发起HTTP请求
        $result = self::httpGet($url);

        // 解析结果
        $result = json_decode($result, true);
        if (!$result || isset($result['errcode'])) {
            Log::error('获取微信用户信息失败: '.json_encode($result, JSON_UNESCAPED_UNICODE));

            return $result ?: [];
        }

        return $result;
    }

    /**
     * 发起HTTP GET请求
     *
     * @param string $url 请求URL
     *
     * @return string 响应内容
     */
    private static function httpGet($url)
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        curl_setopt($ch, CURLOPT_TIMEOUT, 10);
        $result = curl_exec($ch);
        curl_close($ch);

        return $result;
    }
}
